#ifndef GRITC_SERVER_BUFF_HPP
#define GRITC_SERVER_BUFF_HPP

namespace gritc { namespace server {

	template<class Traits> struct buff
	{
		typedef typename Traits::effect_pointer effect_pointer;
		typedef typename Traits::string_type string_type;
		typedef typename Traits::tick_type::time_type time_type;
		typedef unsigned long ulong;

		template<class Function, class Buff, class EffectPointer> struct visit
		{
			Function & function_;
			Buff & buff_;
			EffectPointer & effectptr_;

			visit(Function & f, Buff & b, EffectPointer & e) 
				:	function_(f)
				,	buff_(b)
				,	effectptr_(e) {}

			template<class Effect> void operator()(Effect & effect_)
			{
				function_(buff_,effectptr_,effect_);
			}
		};
		template<class Function> struct closure : buff<Traits>
		{
			Function function;
			closure(string_type const& n, Function const& f) 
				: 	buff(n)
				,	function(f) {}
			virtual ~closure () {}
			virtual void act(effect_pointer & effect_)
			{
				typedef visit<Function,closure<Function>,effect_pointer> Visit;
				(*effect_)(Visit(function,*this,effect_));
			}
		};

		union
		{
			struct
			{
				ulong dispel_bit 	: 1;
				ulong friendly_bit	: 1;
			};
			ulong flag_bits;
		};

		string_type const name_;
		string_type const& name() { return name_; }

		ulong priority;
		time_type ttl;
		
		buff(string_type const& n) 
			: 	name_(n)
			,	flag_bits(0)
			,	priority(50)
			,	ttl(-1) {}

		virtual ~buff() {}
		virtual void act(effect_pointer&) = 0;

		bool operator < (buff<Traits> const& b) const
		{
			return priority < b.priority;
		}
	};

	struct new_buff_
	{
		template<class Buff> 
		typename Buff::traits_type::buff_type::closure<Buff> * operator ()
			(	typename Buff::string_type const& name_
			,	Buff & buff_) const
		{
			return new Buff::traits_type::buff_type::closure<Buff>(name_, buff_);
		}
	} const new_buff;
}}

#endif